
<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Utilities &#8212; libuv documentation</title>
    <link rel="stylesheet" href="../_static/nature.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script src="../_static/jquery.js"></script>
    <script src="../_static/underscore.js"></script>
    <script src="../_static/doctools.js"></script>
    <script src="../_static/language_data.js"></script>
    <link rel="shortcut icon" href="../_static/favicon.ico"/>
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="About" href="about.html" />
    <link rel="prev" title="Advanced event loops" href="eventloops.html" /> 
  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="about.html" title="About"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="eventloops.html" title="Advanced event loops"
             accesskey="P">previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="../index.html">libuv 1.31.0 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../guide.html" accesskey="U">User guide</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Utilities</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="utilities">
<h1>Utilities<a class="headerlink" href="#utilities" title="Permalink to this headline">¶</a></h1>
<p>This chapter catalogues tools and techniques which are useful for common tasks.
The <a class="reference external" href="http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#COMMON_OR_USEFUL_IDIOMS_OR_BOTH">libev man page</a> already covers some patterns which can be adopted to
libuv through simple API changes. It also covers parts of the libuv API that
don’t require entire chapters dedicated to them.</p>
<div class="section" id="timers">
<h2>Timers<a class="headerlink" href="#timers" title="Permalink to this headline">¶</a></h2>
<p>Timers invoke the callback after a certain time has elapsed since the timer was
started. libuv timers can also be set to invoke at regular intervals instead of
just once.</p>
<p>Simple use is to init a watcher and start it with a <code class="docutils literal notranslate"><span class="pre">timeout</span></code>, and optional <code class="docutils literal notranslate"><span class="pre">repeat</span></code>.
Timers can be stopped at any time.</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">uv_timer_t</span> <span class="n">timer_req</span><span class="p">;</span>

<span class="n">uv_timer_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">timer_req</span><span class="p">);</span>
<span class="n">uv_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">timer_req</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="mi">5000</span><span class="p">,</span> <span class="mi">2000</span><span class="p">);</span>
</pre></div>
</div>
<p>will start a repeating timer, which first starts 5 seconds (the <code class="docutils literal notranslate"><span class="pre">timeout</span></code>) after the execution
of <code class="docutils literal notranslate"><span class="pre">uv_timer_start</span></code>, then repeats every 2 seconds (the <code class="docutils literal notranslate"><span class="pre">repeat</span></code>). Use:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">uv_timer_stop</span><span class="p">(</span><span class="o">&amp;</span><span class="n">timer_req</span><span class="p">);</span>
</pre></div>
</div>
<p>to stop the timer. This can be used safely from within the callback as well.</p>
<p>The repeat interval can be modified at any time with:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">uv_timer_set_repeat</span><span class="p">(</span><span class="n">uv_timer_t</span> <span class="o">*</span><span class="n">timer</span><span class="p">,</span> <span class="n">int64_t</span> <span class="n">repeat</span><span class="p">);</span>
</pre></div>
</div>
<p>which will take effect <strong>when possible</strong>. If this function is called from
a timer callback, it means:</p>
<ul class="simple">
<li><p>If the timer was non-repeating, the timer has already been stopped. Use
<code class="docutils literal notranslate"><span class="pre">uv_timer_start</span></code> again.</p></li>
<li><p>If the timer is repeating, the next timeout has already been scheduled, so
the old repeat interval will be used once more before the timer switches to
the new interval.</p></li>
</ul>
<p>The utility function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">uv_timer_again</span><span class="p">(</span><span class="n">uv_timer_t</span> <span class="o">*</span><span class="p">)</span>
</pre></div>
</div>
<p>applies <strong>only to repeating timers</strong> and is equivalent to stopping the timer
and then starting it with both initial <code class="docutils literal notranslate"><span class="pre">timeout</span></code> and <code class="docutils literal notranslate"><span class="pre">repeat</span></code> set to the
old <code class="docutils literal notranslate"><span class="pre">repeat</span></code> value. If the timer hasn’t been started it fails (error code
<code class="docutils literal notranslate"><span class="pre">UV_EINVAL</span></code>) and returns -1.</p>
<p>An actual timer example is in the <a class="reference internal" href="#reference-count"><span class="std std-ref">reference count section</span></a>.</p>
</div>
<div class="section" id="event-loop-reference-count">
<span id="reference-count"></span><h2>Event loop reference count<a class="headerlink" href="#event-loop-reference-count" title="Permalink to this headline">¶</a></h2>
<p>The event loop only runs as long as there are active handles. This system
works by having every handle increase the reference count of the event loop
when it is started and decreasing the reference count when stopped. It is also
possible to manually change the reference count of handles using:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">uv_ref</span><span class="p">(</span><span class="n">uv_handle_t</span><span class="o">*</span><span class="p">);</span>
<span class="n">void</span> <span class="n">uv_unref</span><span class="p">(</span><span class="n">uv_handle_t</span><span class="o">*</span><span class="p">);</span>
</pre></div>
</div>
<p>These functions can be used to allow a loop to exit even when a watcher is
active or to use custom objects to keep the loop alive.</p>
<p>The latter can be used with interval timers. You might have a garbage collector
which runs every X seconds, or your network service might send a heartbeat to
others periodically, but you don’t want to have to stop them along all clean
exit paths or error scenarios. Or you want the program to exit when all your
other watchers are done. In that case just unref the timer immediately after
creation so that if it is the only watcher running then <code class="docutils literal notranslate"><span class="pre">uv_run</span></code> will still
exit.</p>
<p>This is also used in node.js where some libuv methods are being bubbled up to
the JS API. A <code class="docutils literal notranslate"><span class="pre">uv_handle_t</span></code> (the superclass of all watchers) is created per
JS object and can be ref/unrefed.</p>
<p class="rubric">ref-timer/main.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">uv_loop_t</span> <span class="o">*</span><span class="n">loop</span><span class="p">;</span>
<span class="n">uv_timer_t</span> <span class="n">gc_req</span><span class="p">;</span>
<span class="n">uv_timer_t</span> <span class="n">fake_job_req</span><span class="p">;</span>

<span class="nb">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">loop</span> <span class="o">=</span> <span class="n">uv_default_loop</span><span class="p">();</span>

    <span class="n">uv_timer_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">gc_req</span><span class="p">);</span>
<span class="hll">    <span class="n">uv_unref</span><span class="p">((</span><span class="n">uv_handle_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">gc_req</span><span class="p">);</span>
</span>
    <span class="n">uv_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">gc_req</span><span class="p">,</span> <span class="n">gc</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2000</span><span class="p">);</span>

    <span class="o">//</span> <span class="n">could</span> <span class="n">actually</span> <span class="n">be</span> <span class="n">a</span> <span class="n">TCP</span> <span class="n">download</span> <span class="ow">or</span> <span class="n">something</span>
    <span class="n">uv_timer_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">fake_job_req</span><span class="p">);</span>
    <span class="n">uv_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">fake_job_req</span><span class="p">,</span> <span class="n">fake_job</span><span class="p">,</span> <span class="mi">9000</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">uv_run</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>We initialize the garbage collector timer, then immediately <code class="docutils literal notranslate"><span class="pre">unref</span></code> it.
Observe how after 9 seconds, when the fake job is done, the program
automatically exits, even though the garbage collector is still running.</p>
</div>
<div class="section" id="idler-pattern">
<h2>Idler pattern<a class="headerlink" href="#idler-pattern" title="Permalink to this headline">¶</a></h2>
<p>The callbacks of idle handles are invoked once per event loop. The idle
callback can be used to perform some very low priority activity. For example,
you could dispatch a summary of the daily application performance to the
developers for analysis during periods of idleness, or use the application’s
CPU time to perform SETI calculations :) An idle watcher is also useful in
a GUI application. Say you are using an event loop for a file download. If the
TCP socket is still being established and no other events are present your
event loop will pause (<strong>block</strong>), which means your progress bar will freeze
and the user will face an unresponsive application. In such a case queue up and
idle watcher to keep the UI operational.</p>
<p class="rubric">idle-compute/main.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">uv_loop_t</span> <span class="o">*</span><span class="n">loop</span><span class="p">;</span>
<span class="n">uv_fs_t</span> <span class="n">stdin_watcher</span><span class="p">;</span>
<span class="n">uv_idle_t</span> <span class="n">idler</span><span class="p">;</span>
<span class="n">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>

<span class="nb">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">loop</span> <span class="o">=</span> <span class="n">uv_default_loop</span><span class="p">();</span>

    <span class="n">uv_idle_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">idler</span><span class="p">);</span>

    <span class="n">uv_buf_t</span> <span class="n">buf</span> <span class="o">=</span> <span class="n">uv_buf_init</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">1024</span><span class="p">);</span>
    <span class="n">uv_fs_read</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">stdin_watcher</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">on_type</span><span class="p">);</span>
<span class="hll">    <span class="n">uv_idle_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">idler</span><span class="p">,</span> <span class="n">crunch_away</span><span class="p">);</span>
</span>    <span class="k">return</span> <span class="n">uv_run</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>Here we initialize the idle watcher and queue it up along with the actual
events we are interested in. <code class="docutils literal notranslate"><span class="pre">crunch_away</span></code> will now be called repeatedly
until the user types something and presses Return. Then it will be interrupted
for a brief amount as the loop deals with the input data, after which it will
keep calling the idle callback again.</p>
<p class="rubric">idle-compute/main.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">crunch_away</span><span class="p">(</span><span class="n">uv_idle_t</span><span class="o">*</span> <span class="n">handle</span><span class="p">)</span> <span class="p">{</span>
    <span class="o">//</span> <span class="n">Compute</span> <span class="n">extra</span><span class="o">-</span><span class="n">terrestrial</span> <span class="n">life</span>
    <span class="o">//</span> <span class="n">fold</span> <span class="n">proteins</span>
    <span class="o">//</span> <span class="n">computer</span> <span class="n">another</span> <span class="n">digit</span> <span class="n">of</span> <span class="n">PI</span>
    <span class="o">//</span> <span class="ow">or</span> <span class="n">similar</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Computing PI...</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
    <span class="o">//</span> <span class="n">just</span> <span class="n">to</span> <span class="n">avoid</span> <span class="n">overwhelming</span> <span class="n">your</span> <span class="n">terminal</span> <span class="n">emulator</span>
    <span class="n">uv_idle_stop</span><span class="p">(</span><span class="n">handle</span><span class="p">);</span>
<span class="p">}</span>

</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="passing-data-to-worker-thread">
<span id="baton"></span><h2>Passing data to worker thread<a class="headerlink" href="#passing-data-to-worker-thread" title="Permalink to this headline">¶</a></h2>
<p>When using <code class="docutils literal notranslate"><span class="pre">uv_queue_work</span></code> you’ll usually need to pass complex data through
to the worker thread. The solution is to use a <code class="docutils literal notranslate"><span class="pre">struct</span></code> and set
<code class="docutils literal notranslate"><span class="pre">uv_work_t.data</span></code> to point to it. A slight variation is to have the
<code class="docutils literal notranslate"><span class="pre">uv_work_t</span></code> itself as the first member of this struct (called a baton <a class="footnote-reference brackets" href="#id3" id="id1">1</a>).
This allows cleaning up the work request and all the data in one free call.</p>
<div class="highlight-c notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">ftp_baton</span> <span class="p">{</span>
<span class="hll">    <span class="n">uv_work_t</span> <span class="n">req</span><span class="p">;</span>
</span>    <span class="kt">char</span> <span class="o">*</span><span class="n">host</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">port</span><span class="p">;</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">username</span><span class="p">;</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">password</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<div class="highlight-c notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">ftp_baton</span> <span class="o">*</span><span class="n">baton</span> <span class="o">=</span> <span class="p">(</span><span class="n">ftp_baton</span><span class="o">*</span><span class="p">)</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">ftp_baton</span><span class="p">));</span>
<span class="hll"><span class="n">baton</span><span class="o">-&gt;</span><span class="n">req</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span> <span class="n">baton</span><span class="p">;</span>
</span><span class="n">baton</span><span class="o">-&gt;</span><span class="n">host</span> <span class="o">=</span> <span class="n">strdup</span><span class="p">(</span><span class="s">&quot;my.webhost.com&quot;</span><span class="p">);</span>
<span class="n">baton</span><span class="o">-&gt;</span><span class="n">port</span> <span class="o">=</span> <span class="mi">21</span><span class="p">;</span>
<span class="c1">// ...</span>

<span class="n">uv_queue_work</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">baton</span><span class="o">-&gt;</span><span class="n">req</span><span class="p">,</span> <span class="n">ftp_session</span><span class="p">,</span> <span class="n">ftp_cleanup</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p>Here we create the baton and queue the task.</p>
<p>Now the task function can extract the data it needs:</p>
<div class="highlight-c notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">ftp_session</span><span class="p">(</span><span class="n">uv_work_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
<span class="hll">    <span class="n">ftp_baton</span> <span class="o">*</span><span class="n">baton</span> <span class="o">=</span> <span class="p">(</span><span class="n">ftp_baton</span><span class="o">*</span><span class="p">)</span> <span class="n">req</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">;</span>
</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;Connecting to %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">baton</span><span class="o">-&gt;</span><span class="n">host</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">ftp_cleanup</span><span class="p">(</span><span class="n">uv_work_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">ftp_baton</span> <span class="o">*</span><span class="n">baton</span> <span class="o">=</span> <span class="p">(</span><span class="n">ftp_baton</span><span class="o">*</span><span class="p">)</span> <span class="n">req</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">;</span>

    <span class="n">free</span><span class="p">(</span><span class="n">baton</span><span class="o">-&gt;</span><span class="n">host</span><span class="p">);</span>
    <span class="c1">// ...</span>
<span class="hll">    <span class="n">free</span><span class="p">(</span><span class="n">baton</span><span class="p">);</span>
</span><span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>We then free the baton which also frees the watcher.</p>
</div>
<div class="section" id="external-i-o-with-polling">
<h2>External I/O with polling<a class="headerlink" href="#external-i-o-with-polling" title="Permalink to this headline">¶</a></h2>
<p>Usually third-party libraries will handle their own I/O, and keep track of
their sockets and other files internally. In this case it isn’t possible to use
the standard stream I/O operations, but the library can still be integrated
into the libuv event loop. All that is required is that the library allow you
to access the underlying file descriptors and provide functions that process
tasks in small increments as decided by your application. Some libraries though
will not allow such access, providing only a standard blocking function which
will perform the entire I/O transaction and only then return. It is unwise to
use these in the event loop thread, use the <span class="xref std std-ref">libuv-work-queue</span> instead. Of
course, this will also mean losing granular control on the library.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">uv_poll</span></code> section of libuv simply watches file descriptors using the
operating system notification mechanism. In some sense, all the I/O operations
that libuv implements itself are also backed by <code class="docutils literal notranslate"><span class="pre">uv_poll</span></code> like code. Whenever
the OS notices a change of state in file descriptors being polled, libuv will
invoke the associated callback.</p>
<p>Here we will walk through a simple download manager that will use <a class="reference external" href="http://curl.haxx.se/libcurl/">libcurl</a> to
download files. Rather than give all control to libcurl, we’ll instead be
using the libuv event loop, and use the non-blocking, async <a class="reference external" href="http://curl.haxx.se/libcurl/c/libcurl-multi.html">multi</a> interface to
progress with the download whenever libuv notifies of I/O readiness.</p>
<p class="rubric">uvwget/main.c - The setup</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#include &lt;assert.h&gt;</span>
<span class="c1">#include &lt;stdio.h&gt;</span>
<span class="c1">#include &lt;stdlib.h&gt;</span>
<span class="c1">#include &lt;uv.h&gt;</span>
<span class="c1">#include &lt;curl/curl.h&gt;</span>

<span class="hll"><span class="n">uv_loop_t</span> <span class="o">*</span><span class="n">loop</span><span class="p">;</span>
</span><span class="n">CURLM</span> <span class="o">*</span><span class="n">curl_handle</span><span class="p">;</span>
<span class="n">uv_timer_t</span> <span class="n">timeout</span><span class="p">;</span>
<span class="p">}</span>

<span class="nb">int</span> <span class="n">main</span><span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">loop</span> <span class="o">=</span> <span class="n">uv_default_loop</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">curl_global_init</span><span class="p">(</span><span class="n">CURL_GLOBAL_ALL</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Could not init cURL</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="hll">    <span class="p">}</span>
</span>
    <span class="n">uv_timer_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">timeout</span><span class="p">);</span>
<span class="hll">
</span><span class="hll">    <span class="n">curl_handle</span> <span class="o">=</span> <span class="n">curl_multi_init</span><span class="p">();</span>
</span>    <span class="n">curl_multi_setopt</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">,</span> <span class="n">CURLMOPT_SOCKETFUNCTION</span><span class="p">,</span> <span class="n">handle_socket</span><span class="p">);</span>
    <span class="n">curl_multi_setopt</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">,</span> <span class="n">CURLMOPT_TIMERFUNCTION</span><span class="p">,</span> <span class="n">start_timeout</span><span class="p">);</span>

    <span class="k">while</span> <span class="p">(</span><span class="n">argc</span><span class="o">--</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">add_download</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="n">argc</span><span class="p">],</span> <span class="n">argc</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">uv_run</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>
    <span class="n">curl_multi_cleanup</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The way each library is integrated with libuv will vary. In the case of
libcurl, we can register two callbacks. The socket callback <code class="docutils literal notranslate"><span class="pre">handle_socket</span></code>
is invoked whenever the state of a socket changes and we have to start polling
it. <code class="docutils literal notranslate"><span class="pre">start_timeout</span></code> is called by libcurl to notify us of the next timeout
interval, after which we should drive libcurl forward regardless of I/O status.
This is so that libcurl can handle errors or do whatever else is required to
get the download moving.</p>
<p>Our downloader is to be invoked as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ ./uvwget [url1] [url2] ...
</pre></div>
</div>
<p>So we add each argument as an URL</p>
<p class="rubric">uvwget/main.c - Adding urls</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<span class="n">void</span> <span class="n">add_download</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">url</span><span class="p">,</span> <span class="nb">int</span> <span class="n">num</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">char</span> <span class="n">filename</span><span class="p">[</span><span class="mi">50</span><span class="p">];</span>
    <span class="n">sprintf</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">%d</span><span class="s2">.download&quot;</span><span class="p">,</span> <span class="n">num</span><span class="p">);</span>
    <span class="n">FILE</span> <span class="o">*</span><span class="n">file</span><span class="p">;</span>

    <span class="n">file</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s2">&quot;w&quot;</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">file</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Error opening </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">filename</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

<span class="hll">    <span class="n">CURL</span> <span class="o">*</span><span class="n">handle</span> <span class="o">=</span> <span class="n">curl_easy_init</span><span class="p">();</span>
</span><span class="hll">    <span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="n">CURLOPT_WRITEDATA</span><span class="p">,</span> <span class="n">file</span><span class="p">);</span>
</span>    <span class="n">curl_easy_setopt</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="n">CURLOPT_URL</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span>
    <span class="n">curl_multi_add_handle</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">,</span> <span class="n">handle</span><span class="p">);</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Added download </span><span class="si">%s</span><span class="s2"> -&gt; </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">filename</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>We let libcurl directly write the data to a file, but much more is possible if
you so desire.</p>
<p><code class="docutils literal notranslate"><span class="pre">start_timeout</span></code> will be called immediately the first time by libcurl, so
things are set in motion. This simply starts a libuv <a class="reference external" href="Timers">timer</a> which
drives <code class="docutils literal notranslate"><span class="pre">curl_multi_socket_action</span></code> with <code class="docutils literal notranslate"><span class="pre">CURL_SOCKET_TIMEOUT</span></code> whenever it
times out. <code class="docutils literal notranslate"><span class="pre">curl_multi_socket_action</span></code> is what drives libcurl, and what we
call whenever sockets change state. But before we go into that, we need to poll
on sockets whenever <code class="docutils literal notranslate"><span class="pre">handle_socket</span></code> is called.</p>
<p class="rubric">uvwget/main.c - Setting up polling</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39</pre></div></td><td class="code"><div class="highlight"><pre><span></span>
<span class="n">void</span> <span class="n">start_timeout</span><span class="p">(</span><span class="n">CURLM</span> <span class="o">*</span><span class="n">multi</span><span class="p">,</span> <span class="n">long</span> <span class="n">timeout_ms</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">userp</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">timeout_ms</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">timeout_ms</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="o">/*</span> <span class="mi">0</span> <span class="n">means</span> <span class="n">directly</span> <span class="n">call</span> <span class="n">socket_action</span><span class="p">,</span> <span class="n">but</span> <span class="n">we</span><span class="s1">&#39;ll do it in a bit */</span>
    <span class="n">uv_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">timeout</span><span class="p">,</span> <span class="n">on_timeout</span><span class="p">,</span> <span class="n">timeout_ms</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>

<span class="nb">int</span> <span class="n">handle_socket</span><span class="p">(</span><span class="n">CURL</span> <span class="o">*</span><span class="n">easy</span><span class="p">,</span> <span class="n">curl_socket_t</span> <span class="n">s</span><span class="p">,</span> <span class="nb">int</span> <span class="n">action</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">userp</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">socketp</span><span class="p">)</span> <span class="p">{</span>
<span class="hll">    <span class="n">curl_context_t</span> <span class="o">*</span><span class="n">curl_context</span><span class="p">;</span>
</span>    <span class="k">if</span> <span class="p">(</span><span class="n">action</span> <span class="o">==</span> <span class="n">CURL_POLL_IN</span> <span class="o">||</span> <span class="n">action</span> <span class="o">==</span> <span class="n">CURL_POLL_OUT</span><span class="p">)</span> <span class="p">{</span>
<span class="hll">        <span class="k">if</span> <span class="p">(</span><span class="n">socketp</span><span class="p">)</span> <span class="p">{</span>
</span>            <span class="n">curl_context</span> <span class="o">=</span> <span class="p">(</span><span class="n">curl_context_t</span><span class="o">*</span><span class="p">)</span> <span class="n">socketp</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">else</span> <span class="p">{</span>
<span class="hll">            <span class="n">curl_context</span> <span class="o">=</span> <span class="n">create_curl_context</span><span class="p">(</span><span class="n">s</span><span class="p">);</span>
</span>            <span class="n">curl_multi_assign</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="p">(</span><span class="n">void</span> <span class="o">*</span><span class="p">)</span> <span class="n">curl_context</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="n">switch</span> <span class="p">(</span><span class="n">action</span><span class="p">)</span> <span class="p">{</span>
<span class="hll">        <span class="n">case</span> <span class="n">CURL_POLL_IN</span><span class="p">:</span>
</span>            <span class="n">uv_poll_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">curl_context</span><span class="o">-&gt;</span><span class="n">poll_handle</span><span class="p">,</span> <span class="n">UV_READABLE</span><span class="p">,</span> <span class="n">curl_perform</span><span class="p">);</span>
            <span class="k">break</span><span class="p">;</span>
<span class="hll">        <span class="n">case</span> <span class="n">CURL_POLL_OUT</span><span class="p">:</span>
</span>            <span class="n">uv_poll_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">curl_context</span><span class="o">-&gt;</span><span class="n">poll_handle</span><span class="p">,</span> <span class="n">UV_WRITABLE</span><span class="p">,</span> <span class="n">curl_perform</span><span class="p">);</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="n">case</span> <span class="n">CURL_POLL_REMOVE</span><span class="p">:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">socketp</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">uv_poll_stop</span><span class="p">(</span><span class="o">&amp;</span><span class="p">((</span><span class="n">curl_context_t</span><span class="o">*</span><span class="p">)</span><span class="n">socketp</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">poll_handle</span><span class="p">);</span>
                <span class="n">destroy_curl_context</span><span class="p">((</span><span class="n">curl_context_t</span><span class="o">*</span><span class="p">)</span> <span class="n">socketp</span><span class="p">);</span>                
                <span class="n">curl_multi_assign</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="n">default</span><span class="p">:</span>
            <span class="n">abort</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>We are interested in the socket fd <code class="docutils literal notranslate"><span class="pre">s</span></code>, and the <code class="docutils literal notranslate"><span class="pre">action</span></code>. For every socket
we create a <code class="docutils literal notranslate"><span class="pre">uv_poll_t</span></code> handle if it doesn’t exist, and associate it with the
socket using <code class="docutils literal notranslate"><span class="pre">curl_multi_assign</span></code>. This way <code class="docutils literal notranslate"><span class="pre">socketp</span></code> points to it whenever
the callback is invoked.</p>
<p>In the case that the download is done or fails, libcurl requests removal of the
poll. So we stop and free the poll handle.</p>
<p>Depending on what events libcurl wishes to watch for, we start polling with
<code class="docutils literal notranslate"><span class="pre">UV_READABLE</span></code> or <code class="docutils literal notranslate"><span class="pre">UV_WRITABLE</span></code>. Now libuv will invoke the poll callback
whenever the socket is ready for reading or writing. Calling <code class="docutils literal notranslate"><span class="pre">uv_poll_start</span></code>
multiple times on the same handle is acceptable, it will just update the events
mask with the new value. <code class="docutils literal notranslate"><span class="pre">curl_perform</span></code> is the crux of this program.</p>
<p class="rubric">uvwget/main.c - Driving libcurl.</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15</pre></div></td><td class="code"><div class="highlight"><pre><span></span>void curl_perform(uv_poll_t *req, int status, int events) {
<span class="hll">    uv_timer_stop(&amp;timeout);
</span>    int running_handles;
    int flags = 0;
    if (status &lt; 0)                      flags = CURL_CSELECT_ERR;
<span class="hll">    if (!status &amp;&amp; events &amp; UV_READABLE) flags |= CURL_CSELECT_IN;
</span><span class="hll">    if (!status &amp;&amp; events &amp; UV_WRITABLE) flags |= CURL_CSELECT_OUT;
</span>
    curl_context_t *context;

    context = (curl_context_t*)req;
<span class="hll">
</span>    curl_multi_socket_action(curl_handle, context-&gt;sockfd, flags, &amp;running_handles);
    check_multi_info();   
}
</pre></div>
</td></tr></table></div>
<p>The first thing we do is to stop the timer, since there has been some progress
in the interval. Then depending on what event triggered the callback, we set
the correct flags. Then we call <code class="docutils literal notranslate"><span class="pre">curl_multi_socket_action</span></code> with the socket
that progressed and the flags informing about what events happened. At this
point libcurl does all of its internal tasks in small increments, and will
attempt to return as fast as possible, which is exactly what an evented program
wants in its main thread. libcurl keeps queueing messages into its own queue
about transfer progress. In our case we are only interested in transfers that
are completed. So we extract these messages, and clean up handles whose
transfers are done.</p>
<p class="rubric">uvwget/main.c - Reading transfer status.</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">check_multi_info</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">char</span> <span class="o">*</span><span class="n">done_url</span><span class="p">;</span>
    <span class="n">CURLMsg</span> <span class="o">*</span><span class="n">message</span><span class="p">;</span>
    <span class="nb">int</span> <span class="n">pending</span><span class="p">;</span>

<span class="hll">    <span class="k">while</span> <span class="p">((</span><span class="n">message</span> <span class="o">=</span> <span class="n">curl_multi_info_read</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">pending</span><span class="p">)))</span> <span class="p">{</span>
</span>        <span class="n">switch</span> <span class="p">(</span><span class="n">message</span><span class="o">-&gt;</span><span class="n">msg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">case</span> <span class="n">CURLMSG_DONE</span><span class="p">:</span>
<span class="hll">            <span class="n">curl_easy_getinfo</span><span class="p">(</span><span class="n">message</span><span class="o">-&gt;</span><span class="n">easy_handle</span><span class="p">,</span> <span class="n">CURLINFO_EFFECTIVE_URL</span><span class="p">,</span>
</span><span class="hll">                            <span class="o">&amp;</span><span class="n">done_url</span><span class="p">);</span>
</span>            <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> DONE</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">done_url</span><span class="p">);</span>

<span class="hll">            <span class="n">curl_multi_remove_handle</span><span class="p">(</span><span class="n">curl_handle</span><span class="p">,</span> <span class="n">message</span><span class="o">-&gt;</span><span class="n">easy_handle</span><span class="p">);</span>
</span><span class="hll">            <span class="n">curl_easy_cleanup</span><span class="p">(</span><span class="n">message</span><span class="o">-&gt;</span><span class="n">easy_handle</span><span class="p">);</span>
</span>            <span class="k">break</span><span class="p">;</span>

        <span class="n">default</span><span class="p">:</span>
            <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;CURLMSG default</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
            <span class="n">abort</span><span class="p">();</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="check-prepare-watchers">
<h2>Check &amp; Prepare watchers<a class="headerlink" href="#check-prepare-watchers" title="Permalink to this headline">¶</a></h2>
<p>TODO</p>
</div>
<div class="section" id="loading-libraries">
<h2>Loading libraries<a class="headerlink" href="#loading-libraries" title="Permalink to this headline">¶</a></h2>
<p>libuv provides a cross platform API to dynamically load <a class="reference external" href="http://en.wikipedia.org/wiki/Shared_library#Shared_libraries">shared libraries</a>.
This can be used to implement your own plugin/extension/module system and is
used by node.js to implement <code class="docutils literal notranslate"><span class="pre">require()</span></code> support for bindings. The usage is
quite simple as long as your library exports the right symbols. Be careful with
sanity and security checks when loading third party code, otherwise your
program will behave unpredictably. This example implements a very simple
plugin system which does nothing except print the name of the plugin.</p>
<p>Let us first look at the interface provided to plugin authors.</p>
<p class="rubric">plugin/plugin.h</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#ifndef UVBOOK_PLUGIN_SYSTEM</span>
<span class="c1">#define UVBOOK_PLUGIN_SYSTEM</span>

<span class="o">//</span> <span class="n">Plugin</span> <span class="n">authors</span> <span class="n">should</span> <span class="n">use</span> <span class="n">this</span> <span class="n">to</span> <span class="n">register</span> <span class="n">their</span> <span class="n">plugins</span> <span class="k">with</span> <span class="n">mfp</span><span class="o">.</span>
<span class="n">void</span> <span class="n">mfp_register</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span>

<span class="c1">#endif</span>
</pre></div>
</td></tr></table></div>
<p>You can similarly add more functions that plugin authors can use to do useful
things in your application <a class="footnote-reference brackets" href="#id4" id="id2">2</a>. A sample plugin using this API is:</p>
<p class="rubric">plugin/hello.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#include &quot;plugin.h&quot;</span>

<span class="n">void</span> <span class="n">initialize</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">mfp_register</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>Our interface defines that all plugins should have an <code class="docutils literal notranslate"><span class="pre">initialize</span></code> function
which will be called by the application. This plugin is compiled as a shared
library and can be loaded by running our application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ ./plugin libhello.dylib
Loading libhello.dylib
Registered plugin &quot;Hello World!&quot;
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The shared library filename will be different depending on platforms. On
Linux it is <code class="docutils literal notranslate"><span class="pre">libhello.so</span></code>.</p>
</div>
<p>This is done by using <code class="docutils literal notranslate"><span class="pre">uv_dlopen</span></code> to first load the shared library
<code class="docutils literal notranslate"><span class="pre">libhello.dylib</span></code>. Then we get access to the <code class="docutils literal notranslate"><span class="pre">initialize</span></code> function using
<code class="docutils literal notranslate"><span class="pre">uv_dlsym</span></code> and invoke it.</p>
<p class="rubric">plugin/main.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#include &quot;plugin.h&quot;</span>

<span class="n">typedef</span> <span class="n">void</span> <span class="p">(</span><span class="o">*</span><span class="n">init_plugin_function</span><span class="p">)();</span>

<span class="n">void</span> <span class="n">mfp_register</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Registered plugin </span><span class="se">\&quot;</span><span class="si">%s</span><span class="se">\&quot;\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span>
<span class="p">}</span>

<span class="nb">int</span> <span class="n">main</span><span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Usage: </span><span class="si">%s</span><span class="s2"> [plugin1] [plugin2] ...</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>

<span class="hll">    <span class="n">uv_lib_t</span> <span class="o">*</span><span class="n">lib</span> <span class="o">=</span> <span class="p">(</span><span class="n">uv_lib_t</span><span class="o">*</span><span class="p">)</span> <span class="n">malloc</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">uv_lib_t</span><span class="p">));</span>
</span>    <span class="k">while</span> <span class="p">(</span><span class="o">--</span><span class="n">argc</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Loading </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="n">argc</span><span class="p">]);</span>
<span class="hll">        <span class="k">if</span> <span class="p">(</span><span class="n">uv_dlopen</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="n">argc</span><span class="p">],</span> <span class="n">lib</span><span class="p">))</span> <span class="p">{</span>
</span>            <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Error: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">uv_dlerror</span><span class="p">(</span><span class="n">lib</span><span class="p">));</span>
            <span class="k">continue</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="n">init_plugin_function</span> <span class="n">init_plugin</span><span class="p">;</span>
<span class="hll">        <span class="k">if</span> <span class="p">(</span><span class="n">uv_dlsym</span><span class="p">(</span><span class="n">lib</span><span class="p">,</span> <span class="s2">&quot;initialize&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">void</span> <span class="o">**</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">init_plugin</span><span class="p">))</span> <span class="p">{</span>
</span>            <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;dlsym error: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">uv_dlerror</span><span class="p">(</span><span class="n">lib</span><span class="p">));</span>
            <span class="k">continue</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="n">init_plugin</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p><code class="docutils literal notranslate"><span class="pre">uv_dlopen</span></code> expects a path to the shared library and sets the opaque
<code class="docutils literal notranslate"><span class="pre">uv_lib_t</span></code> pointer. It returns 0 on success, -1 on error. Use <code class="docutils literal notranslate"><span class="pre">uv_dlerror</span></code>
to get the error message.</p>
<p><code class="docutils literal notranslate"><span class="pre">uv_dlsym</span></code> stores a pointer to the symbol in the second argument in the third
argument. <code class="docutils literal notranslate"><span class="pre">init_plugin_function</span></code> is a function pointer to the sort of
function we are looking for in the application’s plugins.</p>
</div>
<div class="section" id="tty">
<h2>TTY<a class="headerlink" href="#tty" title="Permalink to this headline">¶</a></h2>
<p>Text terminals have supported basic formatting for a long time, with a <a class="reference external" href="http://en.wikipedia.org/wiki/ANSI_escape_sequences">pretty
standardised</a> command set. This formatting is often used by programs to
improve the readability of terminal output. For example <code class="docutils literal notranslate"><span class="pre">grep</span> <span class="pre">--colour</span></code>.
libuv provides the <code class="docutils literal notranslate"><span class="pre">uv_tty_t</span></code> abstraction (a stream) and related functions to
implement the ANSI escape codes across all platforms. By this I mean that libuv
converts ANSI codes to the Windows equivalent, and provides functions to get
terminal information.</p>
<p>The first thing to do is to initialize a <code class="docutils literal notranslate"><span class="pre">uv_tty_t</span></code> with the file descriptor
it reads/writes from. This is achieved with:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">uv_tty_init</span><span class="p">(</span><span class="n">uv_loop_t</span><span class="o">*</span><span class="p">,</span> <span class="n">uv_tty_t</span><span class="o">*</span><span class="p">,</span> <span class="n">uv_file</span> <span class="n">fd</span><span class="p">,</span> <span class="nb">int</span> <span class="n">unused</span><span class="p">)</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">unused</span></code> parameter is now auto-detected and ignored. It previously needed
to be set to use <code class="docutils literal notranslate"><span class="pre">uv_read_start()</span></code> on the stream.</p>
<p>It is then best to use <code class="docutils literal notranslate"><span class="pre">uv_tty_set_mode</span></code> to set the mode to <em>normal</em>
which enables most TTY formatting, flow-control and other settings. <a class="reference external" href="http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_mode_t">Other</a> modes
are also available.</p>
<p>Remember to call <code class="docutils literal notranslate"><span class="pre">uv_tty_reset_mode</span></code> when your program exits to restore the
state of the terminal. Just good manners. Another set of good manners is to be
aware of redirection. If the user redirects the output of your command to
a file, control sequences should not be written as they impede readability and
<code class="docutils literal notranslate"><span class="pre">grep</span></code>. To check if the file descriptor is indeed a TTY, call
<code class="docutils literal notranslate"><span class="pre">uv_guess_handle</span></code> with the file descriptor and compare the return value with
<code class="docutils literal notranslate"><span class="pre">UV_TTY</span></code>.</p>
<p>Here is a simple example which prints white text on a red background:</p>
<p class="rubric">tty/main.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#include &lt;stdio.h&gt;</span>
<span class="c1">#include &lt;string.h&gt;</span>
<span class="c1">#include &lt;unistd.h&gt;</span>
<span class="c1">#include &lt;uv.h&gt;</span>

<span class="n">uv_loop_t</span> <span class="o">*</span><span class="n">loop</span><span class="p">;</span>
<span class="n">uv_tty_t</span> <span class="n">tty</span><span class="p">;</span>
<span class="nb">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">loop</span> <span class="o">=</span> <span class="n">uv_default_loop</span><span class="p">();</span>

<span class="hll">    <span class="n">uv_tty_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="n">STDOUT_FILENO</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class="hll">    <span class="n">uv_tty_set_mode</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="n">UV_TTY_MODE_NORMAL</span><span class="p">);</span>
</span>    
<span class="hll">    <span class="k">if</span> <span class="p">(</span><span class="n">uv_guess_handle</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="n">UV_TTY</span><span class="p">)</span> <span class="p">{</span>
</span>        <span class="n">uv_write_t</span> <span class="n">req</span><span class="p">;</span>
        <span class="n">uv_buf_t</span> <span class="n">buf</span><span class="p">;</span>
<span class="hll">        <span class="n">buf</span><span class="o">.</span><span class="n">base</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="se">\033</span><span class="s2">[41;37m&quot;</span><span class="p">;</span>
</span>        <span class="n">buf</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="o">.</span><span class="n">base</span><span class="p">);</span>
        <span class="n">uv_write</span><span class="p">(</span><span class="o">&amp;</span><span class="n">req</span><span class="p">,</span> <span class="p">(</span><span class="n">uv_stream_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">uv_write_t</span> <span class="n">req</span><span class="p">;</span>
    <span class="n">uv_buf_t</span> <span class="n">buf</span><span class="p">;</span>
    <span class="n">buf</span><span class="o">.</span><span class="n">base</span> <span class="o">=</span> <span class="s2">&quot;Hello TTY</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">;</span>
    <span class="n">buf</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">buf</span><span class="o">.</span><span class="n">base</span><span class="p">);</span>
    <span class="n">uv_write</span><span class="p">(</span><span class="o">&amp;</span><span class="n">req</span><span class="p">,</span> <span class="p">(</span><span class="n">uv_stream_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>
<span class="hll">    <span class="n">uv_tty_reset_mode</span><span class="p">();</span>
</span>    <span class="k">return</span> <span class="n">uv_run</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The final TTY helper is <code class="docutils literal notranslate"><span class="pre">uv_tty_get_winsize()</span></code> which is used to get the
width and height of the terminal and returns <code class="docutils literal notranslate"><span class="pre">0</span></code> on success. Here is a small
program which does some animation using the function and character position
escape codes.</p>
<p class="rubric">tty-gravity/main.c</p>
<div class="highlight-default notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="c1">#include &lt;stdio.h&gt;</span>
<span class="c1">#include &lt;string.h&gt;</span>
<span class="c1">#include &lt;unistd.h&gt;</span>
<span class="c1">#include &lt;uv.h&gt;</span>

<span class="n">uv_loop_t</span> <span class="o">*</span><span class="n">loop</span><span class="p">;</span>
<span class="n">uv_tty_t</span> <span class="n">tty</span><span class="p">;</span>
<span class="n">uv_timer_t</span> <span class="n">tick</span><span class="p">;</span>
<span class="n">uv_write_t</span> <span class="n">write_req</span><span class="p">;</span>
<span class="nb">int</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">;</span>
<span class="nb">int</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">char</span> <span class="o">*</span><span class="n">message</span> <span class="o">=</span> <span class="s2">&quot;  Hello TTY  &quot;</span><span class="p">;</span>

<span class="n">void</span> <span class="n">update</span><span class="p">(</span><span class="n">uv_timer_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">500</span><span class="p">];</span>

    <span class="n">uv_buf_t</span> <span class="n">buf</span><span class="p">;</span>
    <span class="n">buf</span><span class="o">.</span><span class="n">base</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
<span class="hll">    <span class="n">buf</span><span class="o">.</span><span class="n">len</span> <span class="o">=</span> <span class="n">sprintf</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="s2">&quot;</span><span class="se">\033</span><span class="s2">[2J</span><span class="se">\033</span><span class="s2">[H</span><span class="se">\033</span><span class="s2">[</span><span class="si">%d</span><span class="s2">B</span><span class="se">\033</span><span class="s2">[</span><span class="si">%lu</span><span class="s2">C</span><span class="se">\033</span><span class="s2">[42;37m</span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span>
</span>                            <span class="n">pos</span><span class="p">,</span>
                            <span class="p">(</span><span class="n">unsigned</span> <span class="n">long</span><span class="p">)</span> <span class="p">(</span><span class="n">width</span><span class="o">-</span><span class="n">strlen</span><span class="p">(</span><span class="n">message</span><span class="p">))</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span>
                            <span class="n">message</span><span class="p">);</span>
    <span class="n">uv_write</span><span class="p">(</span><span class="o">&amp;</span><span class="n">write_req</span><span class="p">,</span> <span class="p">(</span><span class="n">uv_stream_t</span><span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span>

<span class="hll">    <span class="n">pos</span><span class="o">++</span><span class="p">;</span>
</span>    <span class="k">if</span> <span class="p">(</span><span class="n">pos</span> <span class="o">&gt;</span> <span class="n">height</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">uv_tty_reset_mode</span><span class="p">();</span>
        <span class="n">uv_timer_stop</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tick</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="nb">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">loop</span> <span class="o">=</span> <span class="n">uv_default_loop</span><span class="p">();</span>

    <span class="n">uv_tty_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="n">STDOUT_FILENO</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">uv_tty_set_mode</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    
<span class="hll">    <span class="k">if</span> <span class="p">(</span><span class="n">uv_tty_get_winsize</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tty</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">width</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">height</span><span class="p">))</span> <span class="p">{</span>
</span>        <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Could not get TTY information</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
        <span class="n">uv_tty_reset_mode</span><span class="p">();</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s2">&quot;Width </span><span class="si">%d</span><span class="s2">, height </span><span class="si">%d</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">);</span>
    <span class="n">uv_timer_init</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">tick</span><span class="p">);</span>
    <span class="n">uv_timer_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">tick</span><span class="p">,</span> <span class="n">update</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">200</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">uv_run</span><span class="p">(</span><span class="n">loop</span><span class="p">,</span> <span class="n">UV_RUN_DEFAULT</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The escape codes are:</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 6%" />
<col style="width: 94%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Code</p></th>
<th class="head"><p>Meaning</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><em>2</em> J</p></td>
<td><p>Clear part of the screen, 2 is entire screen</p></td>
</tr>
<tr class="row-odd"><td><p>H</p></td>
<td><p>Moves cursor to certain position, default top-left</p></td>
</tr>
<tr class="row-even"><td><p><em>n</em> B</p></td>
<td><p>Moves cursor down by n lines</p></td>
</tr>
<tr class="row-odd"><td><p><em>n</em> C</p></td>
<td><p>Moves cursor right by n columns</p></td>
</tr>
<tr class="row-even"><td><p>m</p></td>
<td><p>Obeys string of display settings, in this case green background (40+2), white text (30+7)</p></td>
</tr>
</tbody>
</table>
<p>As you can see this is very useful to produce nicely formatted output, or even
console based arcade games if that tickles your fancy. For fancier control you
can try <a class="reference external" href="http://www.gnu.org/software/ncurses/ncurses.html">ncurses</a>.</p>
<div class="versionchanged">
<p><span class="versionmodified changed">Changed in version 1.23.1:: </span>the <cite>readable</cite> parameter is now unused and ignored.
The appropriate value will now be auto-detected from the kernel.</p>
</div>
<hr class="docutils" />
<dl class="footnote brackets">
<dt class="label" id="id3"><span class="brackets"><a class="fn-backref" href="#id1">1</a></span></dt>
<dd><p>I was first introduced to the term baton in this context, in Konstantin
Käfer’s excellent slides on writing node.js bindings –
<a class="reference external" href="http://kkaefer.github.com/node-cpp-modules/#baton">http://kkaefer.github.com/node-cpp-modules/#baton</a></p>
</dd>
<dt class="label" id="id4"><span class="brackets"><a class="fn-backref" href="#id2">2</a></span></dt>
<dd><p>mfp is My Fancy Plugin</p>
</dd>
</dl>
</div>
</div>


            <div class="clearer"></div>
          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
            <p class="logo"><a href="../index.html">
              <img class="logo" src="../_static/logo.png" alt="Logo"/>
            </a></p>
  <h3><a href="../index.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Utilities</a><ul>
<li><a class="reference internal" href="#timers">Timers</a></li>
<li><a class="reference internal" href="#event-loop-reference-count">Event loop reference count</a></li>
<li><a class="reference internal" href="#idler-pattern">Idler pattern</a></li>
<li><a class="reference internal" href="#passing-data-to-worker-thread">Passing data to worker thread</a></li>
<li><a class="reference internal" href="#external-i-o-with-polling">External I/O with polling</a></li>
<li><a class="reference internal" href="#check-prepare-watchers">Check &amp; Prepare watchers</a></li>
<li><a class="reference internal" href="#loading-libraries">Loading libraries</a></li>
<li><a class="reference internal" href="#tty">TTY</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="eventloops.html"
                        title="previous chapter">Advanced event loops</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="about.html"
                        title="next chapter">About</a></p>
  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="../_sources/guide/utilities.rst.txt"
            rel="nofollow">Show Source</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3 id="searchlabel">Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" />
      <input type="submit" value="Go" />
    </form>
    </div>
</div>
<script>$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="about.html" title="About"
             >next</a> |</li>
        <li class="right" >
          <a href="eventloops.html" title="Advanced event loops"
             >previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="../index.html">libuv 1.31.0 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../guide.html" >User guide</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Utilities</a></li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 2014-present, libuv contributors.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
    </div>
  </body>
</html>